package drds.plus.parser.visitor;

import drds.plus.parser.abstract_syntax_tree.Node;
import drds.plus.parser.abstract_syntax_tree.expression.BinaryExpression;
import drds.plus.parser.abstract_syntax_tree.expression.Pair;
import drds.plus.parser.abstract_syntax_tree.expression.UnaryExpression;
import drds.plus.parser.abstract_syntax_tree.expression.comparison.Is;
import drds.plus.parser.abstract_syntax_tree.expression.comparison.fuzzy_matching.Like;
import drds.plus.parser.abstract_syntax_tree.expression.comparison.range.BetweenAnd;
import drds.plus.parser.abstract_syntax_tree.expression.comparison.range.Equal;
import drds.plus.parser.abstract_syntax_tree.expression.comparison.range.In;
import drds.plus.parser.abstract_syntax_tree.expression.logical.And;
import drds.plus.parser.abstract_syntax_tree.expression.logical.ListExpression;
import drds.plus.parser.abstract_syntax_tree.expression.logical.Or;
import drds.plus.parser.abstract_syntax_tree.expression.primary.function.Function;
import drds.plus.parser.abstract_syntax_tree.expression.primary.function.aggregation.*;
import drds.plus.parser.abstract_syntax_tree.expression.primary.literal.LiteralBoolean;
import drds.plus.parser.abstract_syntax_tree.expression.primary.literal.LiteralNull;
import drds.plus.parser.abstract_syntax_tree.expression.primary.literal.LiteralNumber;
import drds.plus.parser.abstract_syntax_tree.expression.primary.literal.LiteralString;
import drds.plus.parser.abstract_syntax_tree.expression.primary.misc.Identifier;
import drds.plus.parser.abstract_syntax_tree.expression.primary.misc.InList;
import drds.plus.parser.abstract_syntax_tree.expression.primary.misc.ParameterMarker;
import drds.plus.parser.abstract_syntax_tree.expression.primary.misc.RowValues;
import drds.plus.parser.abstract_syntax_tree.expression.primary.subquery.Exists;
import drds.plus.parser.abstract_syntax_tree.statement.*;
import drds.plus.parser.abstract_syntax_tree.statement.select.GroupBy;
import drds.plus.parser.abstract_syntax_tree.statement.select.Limit;
import drds.plus.parser.abstract_syntax_tree.statement.select.OrderBy;
import drds.plus.parser.abstract_syntax_tree.statement.select.table.*;

import java.util.Collection;

public class EmptyVisitor implements Visitor {
    public void visit(Identifier identifier) {
    }

    public void visit(ParameterMarker parameterMarker) {
    }

    public void visit(RowValues rowValues) {
        visitInternal(rowValues.getRowValueList());
    }

    //
    public void visit(InsertStatement insertStatement) {
        visitInternal(insertStatement.getColumnNameList());
        visitInternal(insertStatement.getDuplicateUpdate());
        visitInternal(insertStatement.getRowValuesList());
        visitInternal(insertStatement.getQuery());
        visitInternal(insertStatement.getTableName());
    }

    public void visit(ReplaceStatement replaceStatement) {
        visitInternal(replaceStatement.getColumnNameList());
        visitInternal(replaceStatement.getRowValuesList());
        visitInternal(replaceStatement.getQuery());
        visitInternal(replaceStatement.getTableName());
    }

    public void visit(UpdateStatement updateStatement) {
        visitInternal(updateStatement.getTable());
        visitInternal(updateStatement.getValuePairList());
        visitInternal(updateStatement.getWhere());
    }

    public void visit(DeleteStatement deleteStatement) {
        visitInternal(deleteStatement.getTableName());
        visitInternal(deleteStatement.getWhere());
    }

    public void visit(TruncateStatement truncateStatement) {
        visitInternal(truncateStatement.getTableName());
    }

    public void visit(SelectStatement selectStatement) {
        visitInternal(selectStatement.getGroupBy());
        visitInternal(selectStatement.getHaving());
        visitInternal(selectStatement.getLimit());
        visitInternal(selectStatement.getOrderBy());
        visitInternal(selectStatement.getSelectItemPairList());
        visitInternal(selectStatement.getTables());
        visitInternal(selectStatement.getWhere());
    }

    public void visit(UnionStatement unionStatement) {
        visitInternal(unionStatement.getLimit());
        visitInternal(unionStatement.getOrderBy());
        visitInternal(unionStatement.getSelectStatementList());
    }

    public void visit(OrderBy orderBy) {
        visitInternal(orderBy.getOrderByList());
    }

    public void visit(Limit limit) {
        visitInternal(limit.getOffset());
        visitInternal(limit.getSize());
    }

    public void visit(GroupBy groupBy) {
        visitInternal(groupBy.getGroupByList());
    }

    //
    public void visit(InnerJoin innerJoin) {
        visitInternal(innerJoin.getLeftTable());
        visitInternal(innerJoin.getOn());
        visitInternal(innerJoin.getRightTable());
    }

    public void visit(OuterJoin outerJoin) {
        visitInternal(outerJoin.getLeftTable());
        visitInternal(outerJoin.getOn());
        visitInternal(outerJoin.getRightTable());
    }

    public void visit(SubQuery subQuery) {
        visitInternal(subQuery.getQuery());
    }

    public void visit(Exists exists) {
        visitInternal(exists.getQuery());
    }

    public void visit(Table table) {
        visitInternal(table.getTableName());
    }

    public void visit(Tables tables) {
        visitInternal(tables.getTableList());
    }


    //
    public void visit(Function function) {
        visitInternal(function.getArgList());
    }

    public void visit(Max max) {
        visit((Function) max);
    }

    public void visit(Min min) {
        visit((Function) min);
    }

    public void visit(Sum sum) {
        visit((Function) sum);
    }

    public void visit(Count count) {
        visit((Function) count);
    }

    public void visit(Avg avg) {
        visit((Function) avg);
    }

    //
    public void visit(LiteralNull literalNull) {
    }

    public void visit(LiteralBoolean literalBoolean) {
    }

    public void visit(LiteralNumber literalNumber) {
    }

    public void visit(LiteralString literalString) {
    }

    //
    public void visit(UnaryExpression unaryExpression) {
        visitInternal(unaryExpression.getExpression());
    }

    public void visit(BinaryExpression binaryExpression) {
        visitInternal(binaryExpression.getLeft());
        visitInternal(binaryExpression.getRight());
    }

    //
    public void visit(Or or) {
        visit((ListExpression) or);
    }

    public void visit(And and) {
        visit((ListExpression) and);
    }

    //
    public void visit(Equal equal) {
        visit((BinaryExpression) equal);
    }

    public void visit(Is is) {
        visitInternal(is.getExpression());
    }

    public void visit(Like like) {
        visitInternal(like.getComparee());
        visitInternal(like.getPattern());
        visitInternal(like.getEscape());
    }

    public void visit(BetweenAnd node) {
        visitInternal(node.getComparee());
        visitInternal(node.getNotLessThan());
        visitInternal(node.getNotGreaterThan());
    }

    //
    public void visit(In in) {
        visit((BinaryExpression) in);
    }

    public void visit(ListExpression listExpression) {
        for (int i = 0, len = listExpression.size(); i < len; ++i) {
            visitInternal(listExpression.getExpression(i));
        }
    }

    public void visit(InList inList) {
        visitInternal(inList.getList());
    }

    //
    private void visitInternal(Object obj) {
        if (obj == null)
            return;
        if (obj instanceof Node) {
            ((Node) obj).accept(this);
        } else if (obj instanceof Collection) {
            for (Object o : (Collection) obj) {
                visitInternal(o);
            }
        } else if (obj instanceof Pair) {
            visitInternal(((Pair) obj).getKey());
            visitInternal(((Pair) obj).getValue());
        }
    }


}
